package cpe.hapa.dao;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.PreparedQuery.TooManyResultsException;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.FilterPredicate;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Query.CompositeFilterOperator;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.labs.repackaged.org.json.JSONArray;

import cpe.hapa.model.User;
import static com.google.appengine.api.datastore.FetchOptions.Builder.*;

public class UserDAO {
	public static Key addUser(User user) {
		// TODO : Le champs login doit être unique
		DatastoreService datastore = DatastoreSingleton.getInstance();
		
		Entity u = new Entity("User");
		u.setProperty("nom", user.getNom());
		u.setProperty("prenom", user.getPrenom());
		u.setProperty("dateNaissance", new SimpleDateFormat("yyyy-MM-dd").format(user.getDateNaissance()));
		u.setProperty("email", user.getEmail());
		u.setProperty("login", user.getLogin());
		u.setProperty("password", user.getPassword());
		u.setProperty("role", user.getRole());
		u.setProperty("isPasswordChanged", user.isPasswordChanged());
		u.setProperty("dateCreation", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
		
		return datastore.put(u);
	}
	
	public static void update(User user) throws EntityNotFoundException {
		DatastoreService datastore = DatastoreSingleton.getInstance();
		
		Entity entity = DatastoreSingleton.getInstance().get(user.getKey());
		
		if(user.getDateConnexion() != null) {
			entity.setProperty("dateConnexion", new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(user.getDateConnexion()));
		}
		entity.setProperty("dateNaissance", new SimpleDateFormat("yyyy-MM-dd").format(user.getDateNaissance()));
		entity.setProperty("dureeConnexion", user.getDureeConnexion());
		entity.setProperty("email", user.getEmail());
		entity.setProperty("isPasswordChanged", user.isPasswordChanged());
		entity.setProperty("login", user.getLogin());
		entity.setProperty("nom", user.getNom());
		entity.setProperty("password", user.getPassword());
		entity.setProperty("prenom", user.getPrenom());
		entity.setProperty("role", user.getRole());
		datastore.put(entity);
	}
	
	public static User getByLoginOrEmail(String loginOrEmail) throws NumberFormatException, TooManyResultsException, ParseException {
		DatastoreService datastore = DatastoreSingleton.getInstance();
		Filter loginFilter = new FilterPredicate("login", FilterOperator.EQUAL, loginOrEmail);
		Filter emailFilter = new FilterPredicate("email", FilterOperator.EQUAL, loginOrEmail);
		Query q = new Query("User").setFilter(CompositeFilterOperator.or(loginFilter, emailFilter));
		PreparedQuery pq = datastore.prepare(q);
		Entity e = pq.asSingleEntity();
		if(e == null) {
			return null;
		}
		return createModel(e);
	}
	
	public static User getByKey(Key userKey) throws NumberFormatException, ParseException {
		User user = null;
		
		if(userKey!=null) {
			try {
				DatastoreService datastore = DatastoreSingleton.getInstance();
				Entity entity = datastore.get(userKey);
				user = createModel(entity);
			} catch (EntityNotFoundException e) {
				user = null;
			}
		}
		return user;
	}
	
	public static int count() {
		DatastoreService datastore = DatastoreSingleton.getInstance();
		Query q = new Query("User");
		return datastore.prepare(q).countEntities(withDefaults());
	}
	
	protected static User createModel(Entity entity) throws NumberFormatException, ParseException {
		return new User(
			entity.getKey(),
			String.valueOf(entity.getProperty("nom")),
			String.valueOf(entity.getProperty("prenom")),
			new SimpleDateFormat("yyyy-MM-dd").parse(String.valueOf(entity.getProperty("dateNaissance"))),
			String.valueOf(entity.getProperty("email")),
			String.valueOf(entity.getProperty("login")),
			String.valueOf(entity.getProperty("password")),
			String.valueOf(entity.getProperty("role")),
			Boolean.valueOf(String.valueOf(entity.getProperty("isPasswordChanged"))),
			(entity.getProperty("dateConnexion") != null ? new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").parse(String.valueOf(entity.getProperty("dateConnexion"))) : null),
			(entity.getProperty("dureeConnexion") != null ? Long.valueOf(String.valueOf(entity.getProperty("dureeConnexion"))) : 0),
			new SimpleDateFormat("yyyy-MM-dd").parse(String.valueOf(entity.getProperty("dateCreation")))
		);
	}
	
	public static ArrayList<User> getAll() throws NumberFormatException, ParseException {
		ArrayList<User> listUser = new ArrayList<User>();
		
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		
		Query userListQuery = new Query("User");
		
		PreparedQuery preparedQuery = datastore.prepare(userListQuery);
		
		for(Entity result : preparedQuery.asIterable())
		{
			listUser.add(createModel(result));
		}
		return listUser;
	}
}
